module.exports = (EdtApi) => {
    "use strict";
    let chatId = "", id = "", unread = 0, indexdb, dbVersion = 1, globalData, chat, ck, badges, count = 0, chatObserver;
    function setTheme(theme = "light") {
        if (1 == 1) return;
        // let classList = document.body?.classList;
        // if (!classList) return;
        // classList.remove("dark" == theme ? "theme-light" : "theme-dark");
        // classList.add("dark" == theme ? "theme-dark" : "theme-light");
        // document.querySelector("html")?.setAttribute("style", themeInfo[theme].html);
        // document.body?.setAttribute("style", themeInfo[theme].body);
        // document.querySelector("#MiddleColumn")?.setAttribute("style", themeInfo[theme].MiddleColumn);
        // document.querySelector('head>meta[name="theme-color"]')?.setAttribute("content", themeInfo[theme].themeColor);
    }
    window.addEventListener('load', () => {
        setTimeout(() => {
            setTheme(localStorage.getItem("edt-theme") || "light");
        }, 500);
    });
    async function getChatId(times = 0) {
        id = window.location.hash?.replace("#", "") || "";
        if (id && id != chatId) return id;
        await EdtApi.sleep(100);
        if (times > 10) return id;
        times++;
        return getChatId(times);
    }
    function getNodeContent(node, status) {
        let text = "";
        switch (node.nodeName) {
            case "#text":
                text = node.textContent;
                if (!status.hasText) status.hasText = !!node.textContent;
                break;
            case "IMG":
                text = node.alt;
                break;
            case "BR":
                text = "\n";
                break;
            case "A":
                text = node.textContent;
                if (!status.hasText) status.hasText = !!node.textContent;
                break;
            case "STRONG":
                node.childNodes?.forEach((child) => {
                    text += getNodeContent(child, status);
                });
                break;
            case "EM":
                text = node.textContent;
                if (!status.hasText) status.hasText = !!node.textContent;
                break;
            case "SPAN":
                if ("true" != node.getAttribute("data-ignore-on-paste")) {//忽略时间
                    text = node.textContent;
                    if (!status.hasText) status.hasText = !!node.textContent;
                }
                break;
            default:
                text = node.textContent;
                if (!status.hasText) status.hasText = !!node.textContent;
                break;
        }
        return text;
    }
    function getMsgId(msgBox) {
        let message = EdtApi.closest(msgBox, "div.message-list-item");
        return message?.getAttribute('data-message-id');
    }
    function openDB(dbName) {
        return new Promise(resolve => {
            let indexedDB = window.indexedDB;
            const request = indexedDB?.open(dbName, dbVersion);
            if (!request) return resolve(null);
            request.onsuccess = event => {
                indexdb = event.target?.result; // 数据库对象
                resolve(indexdb);
            };
            request.onerror = async (event) => {
                let message = event?.target?.error?.message;
                if (message?.includes("existing version (")) {
                    let arr = message.split("existing version (");
                    dbVersion = parseInt(arr[1].split(")")[0]);
                    console.log("dbVersion", dbVersion);
                }
                resolve(await openDB(dbName));
            }
        });
    }
    async function getVoiceId(msgId, chatId) {
        return new Promise((resolve) => {
            getDbData("tt-global-state").then(data => {
                if (!data) return resolve("");
                let messages = data?.messages?.byChatId?.[chatId]?.byId;
                let value = messages?.[msgId]?.content?.voice?.id
                resolve(value);
            }).catch(() => {
                resolve("");
            });
        });
    }
    async function getDbData(key) {
        if (!document.querySelector("#Main")) return Promise.resolve(null);
        let dbName = "tt-data", storeName = "store";
        if (!indexdb) await openDB(dbName);
        return new Promise((resolve) => {
            let transaction = indexdb?.transaction([storeName]);
            let objectStore = transaction?.objectStore(storeName);
            let request = objectStore?.get(key);
            if (!request) return resolve(null);
            request.onsuccess = () => {
                globalData = request?.result;
                resolve(globalData);
            };
            request.onerror = () => {
                resolve(null);
            };
        });
    }
    function getVoiceFile(voiceId) {
        return new Promise(async (resolve) => {
            try {
                let cacheName = 'tt-media-progressive'  // 定义cache名称
                let path = `/a/progressive/document${voiceId}`   // 定义路径
                let cachesLocal = await caches.has(cacheName);
                console.log(voiceId, cachesLocal);
                if (!cachesLocal) return resolve(null);
                //如果当前已有数据则直接获取缓存的数据
                caches.match(path, { ignoreSearch: true, cacheName }).then(async res => {
                    resolve(await res.arrayBuffer());
                }).catch(() => {
                    resolve(null);
                })
            } catch (error) {
                resolve(null);
            }
        })
    }
    function getUserAvatar(userId) {
        return new Promise(async (resolve) => {
            try {
                let cacheName = 'tt-media-avatars'  // 定义cache名称
                let path = `/a/avatar${userId}`   // 定义路径
                let cachesLocal = await caches.has(cacheName)
                if (!cachesLocal) return resolve(null);
                //如果当前已有数据则直接获取缓存的数据
                caches.match(path, { ignoreSearch: true, cacheName }).then(async res => {
                    resolve(await res.arrayBuffer());
                }).catch(() => {
                    resolve(null);
                })
            } catch (error) {
                resolve(null);
            }
        })
    }
    function getUnread() {
        unread = 0;
        getDbData("tt-global-state").then(data => {
            if (!data) return;
            let chats = data?.chats?.byId || {};
            let archiveds = data?.chats?.listIds?.archived || [];
            let active = data?.chats?.listIds?.active || [];
            for (ck in chats) {
                chat = chats[ck];
                if (ck < 0) continue;
                if (!chat || chat.isMuted) continue;
                if (archiveds?.includes(chat.id)) continue;
                if (!active.includes(chat.id)) continue;
                if (JSON.stringify(chat.usernames || [])?.toLocaleLowerCase().includes("bot")) continue;
                // if (chat.unreadCount) console.log("getUnread:::", chat);
                unread += chat.unreadCount || 0;
            }
        }).catch((err) => { console.log(err); });
    }
    return {
        config: {
            friendList: ".Transition_slide.Transition_slide-active .chat-list,.Transition_slide.Transition_slide-active .search-section,.Transition_slide.Transition_slide-active .search-content,.top-peers-section>.top-peers",
            chat: "#MiddleColumn div.messages-layout",
            input: 'div.messages-layout div.Transition div.Transition_slide.Transition_slide-active div.form-control[contenteditable][role="textbox"]',
            msgBox: ".messages-layout .Transition_slide-active .MessageList",
            inMsg: "div.MessageList .message-list-item:not(.own) .message-content:not(.voice) .content-inner:not(.trans-inited)",
            outMsg: "div.MessageList .message-list-item.own .message-content:not(.voice) .content-inner:not(.trans-inited)",
            allMsg: "div.MessageList .message-list-item .content-inner",
            voiceMsg: '.message-content.voice .Audio:not(.trans-inited)',
            outVoice: {
                selector: ".message-list-item.own",
                level: 10,
            },
            sendBtn: "div.Transition_slide-active div.Composer>button.Button.send",
            setting: ".messages-layout div.Transition_slide.Transition_slide-active div.middle-column-footer div.message-input-wrapper #message-input-text",
            files: {
                sendBtn: "div.Modal.open div.wDqWK9MD>button.Button",
                event: "mousedown",
            },
            tips: {
                in: "div.MiddleHeader div.Transition_slide.Transition_slide-active .chat-info-wrapper>div.ChatInfo>div.info",
                out: "div.Transition>div.Transition_slide.Transition_slide-active>div.middle-column-footer",
            },
            placeholder: {
                selector: "div.messages-layout>div.Transition>div.Transition_slide.Transition_slide-active .placeholder-text",
            },
            // userInfo: {
            //     selector: "div.MenuItem",
            //     level: 3,
            // },
            crm: {
                listener: '#LeftColumn',
                top: 'div.MiddleHeader div.Transition_slide.Transition_slide-active .chat-info-wrapper>div.ChatInfo>div.info>.title',
            },
            contextmenu: {
                enable: true,
                selector: "div.MediaViewerContent"
            },
            extra: {//其他会触发对话框变动的情况处理
                selector: 'a.Link,a.ChatLink,.back-button,button[title="Back"],.text-entity-link,.message-title,.members-list,.Avatar,.Transition_slide-active.ChatOrUserPicker_slide,div.messages-layout>div.MiddleHeader button[aria-label="Pinned messages"]',
                level: 20,
                delay: 600,
            },
            autoCount: 20,
            mainRequest: true,
            inputType: "input",
            funcs: {
                fansDupl: true,
                workOrder: true,
                chatRecord: true
            }
        },
        init(handler) {
            let btn;
            document.addEventListener('dblclick', e => {
                btn = EdtApi.closest(e.target, ".trans-info", 5);
                if (btn) {
                    e.preventDefault();
                    e.stopPropagation();
                    e.stopImmediatePropagation();
                }
            }, {
                capture: true,
                passive: false
            });
            EdtApi.queryWait({ selector: "#MiddleColumn", timeout: 10000 }).then((box) => {
                // console.log(box);
                let observer = new MutationObserver((mutations) => {
                    // console.log(mutations);
                    mutations.forEach((mutation) => {
                        if (mutation?.addedNodes?.length > 0) {
                            if (mutation.addedNodes[0]?.classList?.contains("messages-layout")) this.initChat(handler);
                        }
                    });
                });
                observer?.observe(box, {
                    childList: true,
                    subtree: false
                });
            }).catch((err) => { console.log(err); });
        },
        initChat(handler) {
            handler.initChat(null);
            EdtApi.queryWait({ selector: "#MiddleColumn>div.messages-layout", timeout: 10000 }).then((box) => {
                // console.log(box);
                chatObserver?.disconnect();
                chatObserver = null;
                chatObserver = new MutationObserver((mutations) => {
                    // console.log(mutations);
                    handler.initChat(null);
                });
                chatObserver?.observe(box, {
                    childList: true,
                    subtree: false
                });
            }).catch((err) => { console.log(err); });
        },
        getFriendAvatar(friendId) {
            return getUserAvatar(friendId);
        },
        getMessageRecords({ handler, chatId }) {//获取聊天记录
            return new Promise((resolve) => {
                if (chatId < 0) return resolve({});//群消息不处理
                EdtApi.sleep(1000).then(async () => {//等待消息列表加载完成
                    await getDbData("tt-global-state");
                    chatId = await getChatId();
                    if (chatId < 0) return resolve({});
                    let friendName = this.getChatTitle();
                    let messageInfo = globalData?.messages?.byChatId?.[chatId]?.byId || {}, message, records = [], id, content;
                    // console.log("messageInfo:::", messageInfo);
                    for (id in messageInfo) {
                        message = messageInfo[id];
                        if (!message) continue;
                        content = message.content?.text?.text + "";
                        if (!content || "undefined" === content) continue;
                        records.push({
                            id,
                            content,
                            msgType: 1,
                            time: message.date * 1000,
                            isSend: message.isOutgoing,
                            transContent: handler.transCache[content],
                            timeString: EdtApi.formatDateTime(message.date * 1000),
                        });
                    }
                    resolve({
                        records,
                        friendName,
                        friendId: chatId,
                    });
                });
            });
        },
        async getWorkOrderInfos() {//获取工单信息
            if (!globalData) await getDbData("tt-global-state");
            let userInfo = globalData?.chats?.byId || {}, infos = [], key;
            for (key in userInfo) {
                if (key < 0) continue;
                infos.push({
                    fansId: key,
                    fansName: userInfo[key].title
                });
            }
            return infos;
        },
        async getFriends() {
            if (!globalData) await getDbData("tt-global-state");
            let userInfo = globalData?.chats?.byId || {};
            let friends = [], key, usernames, avatar;
            for (key in userInfo) {
                if (key < 0) continue;
                usernames = userInfo[key]?.usernames;
                avatar = await getUserAvatar(key);
                friends.push({
                    id: key,
                    avatar: avatar ? Buffer.from(avatar) : null,
                    name: userInfo[key].title,
                    account: usernames?.[0].username || "",
                });
            }
            console.log("friends:::", friends);
            return friends;
        },
        async getChats() {//获取工单信息
            await getDbData("tt-global-state");
            let chats = globalData?.chats?.listIds.active || [], chatIds = [];
            for (key in chats) {
                if (key < 0) continue;
                chatIds.push(key);
            }
            console.log("getChats:::", chatIds);
            return chatIds;
        },
        setTheme({ theme }) {
            localStorage.setItem("edt-theme", theme);
            setTheme(theme);
        },
        getUnread() {
            let count = unread;
            getUnread();
            let eleCount = this.getEleUnread();
            return count > eleCount ? count : eleCount;
        },
        getEleUnread() {
            count = 0;
            let newEl, text = "";
            badges = document.querySelectorAll("#LeftColumn-main .ListItem .subtitle .unread:not(.muted)");
            badges?.forEach(badge => {
                text = "";
                newEl = badge?.querySelector(".Jw1oQFdk");
                if (newEl) {
                    badge?.querySelectorAll("span.tgKbsVmz>span")?.forEach(span => {
                        text += span?.textContent || "";
                    });
                    text += newEl.textContent || "";
                } else text = badge?.textContent || "0";
                count += EdtApi.safeParseInt(text || "0");
            });
            return count;
        },
        getItemByChatId(chatId) {
            return document.querySelector(`#LeftColumn div.chat-list div.ListItem a.ListItem-button[href="#${chatId}"]>div.info`);
        },
        isCanScroll(e) {
            if (!e) return false;
            let target = e.srcElement || e.target;
            if (!target) return false;
            if (document.querySelector("#telegram-search-input")?.value) return false;
            if (document.querySelector(this.config.friendList)?.contains(target)) return true;
            return false;
        },
        getChatInfo(e) {
            let canScroll = this.isCanScroll(e);//必须在此处判断，不然页面元素可能会变动
            // console.log("canScroll:", canScroll);
            return new Promise(async (resolve) => {
                chatId = await getChatId();
                resolve({ id: chatId, isGroup: chatId?.includes("-") });
                canScroll && this.scrollToBottom();
            });
        },
        getChatIds() {
            getDbData("tt-global-state");
            let listIds = globalData?.chats?.listIds || {};
            let ids = [], key;
            for (key in listIds) ids = ids.concat(listIds[key]);
            return ids;
        },
        getChatTitle(chatEl = document) {
            let titleEl = chatEl.querySelector(
                "div.MiddleHeader div.Transition_slide.Transition_slide-active .chat-info-wrapper>div.ChatInfo>div.info>div.title>h3"
            );
            if (!titleEl) return "";
            if (!titleEl.querySelector(".emoji")) return titleEl.textContent || "";
            let title = "";
            titleEl.childNodes?.forEach((child) => {
                if (child.nodeName == "#text") {
                    title += child.textContent || "";
                } else if (child.nodeName == "IMG") {
                    title += child.alt || "";
                }
            });
            return title;
        },
        getText(msgBox) {
            let texts = [],
                text = "", status = {
                    hasText: false
                };
            try {
                let textEls = msgBox.querySelectorAll(".text-content,.site-title,.site-description");
                textEls?.forEach((el) => {
                    text = "";
                    el.childNodes?.forEach((child) => {
                        text += getNodeContent(child, status);
                    });
                    texts.push(text);
                });
            } catch (error) {
                console.error(error);
            }
            if (!status.hasText) return "";
            return texts.join("\n");
        },
        getIptText(inputEl) {
            return inputEl?.textContent || "";
        },
        getIptMsg(inputEl) {
            if (!inputEl) return "";
            console.log("getIptMsg:::", inputEl, inputEl?.textContent);
            let value = "";
            try {
                value = inputEl.textContent;
                if (!value) return "";//纯表情不翻译
                value = "";
                inputEl.childNodes?.forEach((child) => {
                    if (child.nodeName == "#text") {
                        value += child.textContent;
                    } else if (child.nodeName == "IMG") {
                        value += child.alt;
                    } else if (child.nodeName == "BR") {
                        value += "\n";
                    } else if (child.nodeName == "I") {
                        value += child.textContent;
                    } else if (child.nodeName == "DIV") {
                        if (value) value += "\n";
                        value += child.textContent;
                    } else value += child.textContent;
                });
            } catch (error) {
                console.error(error);
            }
            return value;
        },
        async getVoice(msgBox) {
            let chatId = window.location.hash?.replace('#', '');
            let msgId = getMsgId(msgBox);
            let voiceId = await getVoiceId(msgId, chatId);
            if (!voiceId) return null;
            let file = await getVoiceFile(voiceId);
            return {
                file,
                msgId,
                format: "ogg"
            }
        },
        getImg(msgBox) {
            return new Promise((resolve) => {
                EdtApi.queryWait({ selector: "img.full-media", parent: msgBox, timeout: 500 }).then((img) => {
                    resolve(img);
                }).catch(() => { })
            });
        },
        getMsgId(msgBox) {
            return getMsgId(msgBox);
        },
        beforeSend({ handler }) {
            //发送前处理特殊情况
            let obj = {
                result: true,
                fileInput: null,
            };
            return new Promise((resolve) => {
                let fileModal = document.querySelector("#portals div.Modal.open");
                if (!fileModal) return resolve(obj);
                let fileInput = fileModal.querySelector("#editable-message-text-modal");
                if (!fileInput) return resolve(obj);
                obj.fileInput = fileInput;
                let msg = this.getIptMsg(fileInput);
                if (!handler.sendTrans(msg)) return resolve(obj);
                handler.transToInput(fileInput, msg).then((result) => {
                    obj.result = result;
                    resolve(obj);
                }).catch((error) => {
                    handler.showLoading({
                        msg: error.message || "翻译失败！",
                        type: "error",
                    });
                    obj.result = false;
                    resolve(obj);
                });
            });
        },
        scrollToBottom() {
            let num = 0, el, timer = setInterval(() => {
                el = document.querySelector(".MessageList");
                if (el) el.scrollTop = el.scrollHeight;
                num++;
                if (num >= 2) {
                    clearInterval(timer);
                    timer = null;
                    el = null;
                }
            }, 200);
        },
        getUserInfo() {
            try {
                if (!globalData) {
                    getDbData('tt-global-state');
                    return null;
                } else {
                    let userId = globalData?.currentUserId;
                    let info = globalData?.users?.byId?.[userId];
                    let fullInfo = globalData?.users?.fullInfoById?.[userId];
                    let account = userId || info?.phoneNumber || "";
                    let avatar = fullInfo?.profilePhoto?.thumbnail?.dataUri || "";
                    let userName = "";
                    if (info?.usernames?.length > 0) userName = info.usernames[0].username;
                    if (!userName) userName = `${info?.firstName}${info?.lastName ? "-" + info?.lastName : ""}`;
                    return {
                        avatar,
                        account,
                        userName,
                    };
                }
            } catch (error) {
                return null;
            }
        },
        async getCurrentUserInfo() {
            try {
                if (!globalData) await getDbData("tt-global-state");
                let userId = globalData?.currentUserId;
                let info = globalData?.users?.byId?.[userId];
                let fullInfo = globalData?.users?.fullInfoById?.[userId];
                let account = userId || info?.phoneNumber || "";
                let userName = "";
                if (info?.usernames?.length > 0) userName = info.usernames[0].username;
                if (!userName) userName = `${info?.firstName}${info?.lastName ? "-" + info?.lastName : ""}`;
                let avatar = await getUserAvatar(userId);
                if (!avatar) avatar = fullInfo?.profilePhoto?.thumbnail?.dataUri || "";
                // console.log(userId, avatar, account, userName);
                return {
                    avatar,
                    account,
                    userName
                };
            } catch (error) {
                return null;
            }
        }
    };
};